package DataStructure.stringOps.stringAndSequence;

import Common.Constant.C;
import Common.Utils.UTFactory;
import org.junit.Test;

import java.util.Objects;

/**
 * @author 蔚蔚樱
 * @version 1.0
 * @date 2018-5-13 Time：下午10:31:25
 * @author—Email micromicrohard@outlook.com
 * @description 人民币大小写转换
 * digital trans to capital
 * 要求：
 * 1、输入不仅包括整数，还有可能包括小数，数字间存在空格的需要处理
 * 2、以0开头的不正确(022,02.2)，除了0.x
 * 3、整数部分需要在结尾处标记"圆"，整数部分全部为0的则不进行标记
 * 4、当中间有0的时候，需要标记"零"，当存在连续多个0时，需要省略为一个"零"
 * 5、人民币大写表示："零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"
 * 6、人民币单位包括："厘","毫","分","角","拾", "佰", "仟", "万","亿"
 * <p>
 * method:
 * 1.去空格.
 * 2.数字判断：
 * 2.1 除了一个小数点和多个数字，其他字符都不对。
 * 2.2 以0开头的不正确(022,02.2)，除了0.x
 * 3.分成整数和小数部分处理
 * 4.整数和小数部分合并，去零.
 */

public class DigitalTrans {

    @Test // 验证功能：从数据库获取测试数据，用于单元测试
    public void TestFunc() throws Exception {
        UTFactory.FullTest(this.getClass());
    }

    @Test // 调试功能 : 用于复现错误的测试案例
    public void DoubleTrack() throws Exception {
        String input = "1";
        String output = "壹圆";
        UTFactory.DebugTest(this.getClass(), input, output);
    }

    String[] digital = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
    String[] unitBeforePoint = {"圆", "拾", "佰", "仟", "万", "拾万", "佰万", "仟万", "亿", "拾亿", "佰亿", "仟亿"};
    String[] unitAfterPoint = {"角", "分", "毫", "厘"};
    String num = "";

    public String transMethod(String num) {
        this.num = num;
        StringBuffer sb = new StringBuffer();
        // 1、字符串校验
        if (!check()) {
            return C.ErrorExpr;
        }
        // 3.分成整数和小数部分处理 —— 预处理
        dealInteger(sb);//3.1、处理整数部分
        dealDecimal(sb);//3.2、处理小数部分
        // 4.整数和小数部分合并，去零
        return sb.toString().equals("") ? "零圆" : sb.toString();
    }

    // 字符串校验 并去空格
    private boolean check() {
        //1.去空格，考虑到字符串中间含有空格，不要使用num = num.trim();
        this.num.replaceAll("\\s*", "");

        //2.数字判断:
        //  1) 除了一个小数点和多个数字，其他字符都不对。
        //  2) 以0开头的不正确(022,02.2)，除了0.x
        String pattern = "[0-9]|^[1-9]+[0-9]*$|^0\\.[0-9]+$|^[1-9]+[0-9]*\\.[0-9]+$"; //正则 grammar
        return this.num.matches(pattern); //throw new Exception("钱数格式错误！");
    }

    // 处理整数
    private void dealInteger(StringBuffer sb) {
        String[] deal = this.num.split("\\.");
        if (deal.length > 2) {
            return;
        }
        String integerPart = deal[0];
        //整数部分最多只保留 十二位，仅用于测试
        if (deal[0].length() > 12) {
            int k = deal[0].length() - 12;
            integerPart = deal[0].substring(k);
        }

        // flag合并零的标志位
        boolean zeroFlag = false;
        int index = integerPart.length() - 1;

        for (int i = 0; i < integerPart.length(); i++) {
            // 遇见非连续的0时进行合并操作
            if (!zeroFlag && integerPart.charAt(i) == '0') {
                sb.append("零");
                zeroFlag = true;
            }
            // 附加数值
            if (integerPart.charAt(i) != '0') {
                sb.append(digital[integerPart.charAt(i) - '0']).append(unitBeforePoint[index]);
                zeroFlag = false;
            }
            // 计量单位是从后往前计算的
            index--;
        }
        // 如果整数以零结尾，则替换成圆
        if (sb.lastIndexOf("零") == sb.length() - 1) {
            sb.replace(sb.length() - 1, sb.length(), "圆");
        }
        // 如果整数部分仅包括零，如0.1，则直接去掉(因为仅包括零的被替换成圆，所以以圆作为匹配)
        if (sb.toString().equals("圆")) {
            sb.delete(0, sb.length()); //attention 错误写法：sb = new StringBuffer();
            return;
        }

        // 整数部分友好输出
        while (sb.lastIndexOf("万") != sb.indexOf("万")) { // 例子：叁拾"万"肆万玖仟柒佰陆拾圆 => 叁拾肆万玖仟柒佰陆拾圆
            int cut = sb.indexOf("万");
            sb.replace(cut, cut + 1, "");
        }
        while (sb.lastIndexOf("亿") != sb.indexOf("亿")) {
            int cut = sb.indexOf("亿");
            sb.replace(cut, cut + 1, "");
        }
    }

    // 处理小数
    private void dealDecimal(StringBuffer sb) {
        String[] deal = this.num.split("\\.");
        if (deal.length != 2) {
            return;
        }
        boolean zeroFlag = false;    // zeroFlag:合并零的标志位
        int index = 0;
        String decimal = deal[1];
        if (deal[1].length() > 4) {  // 小数部分最多只保留小数点后四位，仅用于测试
            decimal = deal[1].substring(0, 4);
        }

        for (int i = 0; i < decimal.length(); i++) {
            //遇见非连续的0进行合并操作
            if (!zeroFlag && decimal.charAt(i) == '0') {
                sb.append("零");
                zeroFlag = true;
            }
            if (decimal.charAt(i) != '0') {
                sb.append(digital[decimal.charAt(i) - '0']).append(unitAfterPoint[index]);
                zeroFlag = false;
            }
            index++;
        }
        //小数以零结尾，则直接去掉
        while (sb.lastIndexOf("零") == sb.length() - 1) {
            sb.replace(sb.length() - 1, sb.length(), "");
        }
        //小数部分不应该以零开头
        if (sb.indexOf("零") == 0) {
            sb.replace(0, 1, "");
        }
    }
}

